﻿//------------------------------------------------------------------------------
// <copyright file="Crypto.cs" company="Robert MacLean">
//      Copyright © Robert MacLean.  All Rights Reserved.
// </copyright>
//
//  Details on this see: http://pepper.codeplex.com
//  This code released under the terms of the 
//  Microsoft Public License  (MS-PL, http://opensource.org/licenses/ms-pl.html.)
//------------------------------------------------------------------------------

namespace Pepper.Core
{
    using System;
    using System.IO;
    using System.Security.Cryptography;

    internal static class Crypto
    {
        public static string Hash(this string input)
        {
            using (var hash = new SHA256Managed())
            {
                return Convert.ToBase64String(hash.ComputeHash(System.Text.Encoding.UTF8.GetBytes(input)));
            }
        }

        public static byte[] EncryptToBytes(this string plainText, string key)
        {
            MemoryStream msEncrypt = null;
            var aesAlg = new RijndaelManaged();
            try
            {
                var salt = new byte[] { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0xF1, 0xF0, 0xEE, 0x21, 0x22, 0x45 };
                using (var rfc = new Rfc2898DeriveBytes(key, salt))
                {
                    // Create a RijndaelManaged object// with the specified key and IV.
                    aesAlg.Key = rfc.GetBytes(16);
                    aesAlg.IV = rfc.GetBytes(16);
                }

                using (var encryptor = aesAlg.CreateEncryptor(aesAlg.Key, aesAlg.IV))
                {
                    // Create the streams used for encryption.
                    msEncrypt = new MemoryStream();
                    using (var csEncrypt = new CryptoStream(msEncrypt, encryptor, CryptoStreamMode.Write))
                    {
                        using (var swEncrypt = new StreamWriter(csEncrypt))
                        {
                            swEncrypt.Write(plainText);
                        }
                    }
                }

            }
            finally
            {
                aesAlg.Clear();
            }

            return msEncrypt.ToArray();
        }

        public static string EncryptToString(this string plainText, string key)
        {            
            return Convert.ToBase64String(EncryptToBytes(plainText, key));
        }

        public static string DecryptFromBytes(this byte[] cipherText, string key)
        {
            var aesAlg = new RijndaelManaged();
            try
            {
                var salt = new byte[] { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0xF1, 0xF0, 0xEE, 0x21, 0x22, 0x45 };
                using (var rfc = new Rfc2898DeriveBytes(key, salt))
                {
                    aesAlg.Key = rfc.GetBytes(16);
                    aesAlg.IV = rfc.GetBytes(16);
                }

                using (var decryptor = aesAlg.CreateDecryptor(aesAlg.Key, aesAlg.IV))
                {
                    using (var msDecrypt = new MemoryStream(cipherText))
                    {
                        using (var csDecrypt = new CryptoStream(msDecrypt, decryptor, CryptoStreamMode.Read))
                        {
                            using (var srDecrypt = new StreamReader(csDecrypt))

                                return srDecrypt.ReadToEnd();
                        }
                    }
                }
            }
            finally
            {
                aesAlg.Clear();
            }
        }

        public static string DecryptFromString(this string input, string key)
        {
            return Convert.FromBase64String(input).DecryptFromBytes(key);
        }
    }
}
